//
//  TJNetworking.m
//  BaoDian
//
//  Created by mac on 2024/8/4.
//

#import "TJNetworking.h"
#import "TJLoadingView.h"
#import "TJAlertController.h"
#import <MBProgressHUD.h>
#import "TJGlobalFunction.h"

@interface TJNetworking()<NSURLSessionDelegate>

@property (nonatomic, strong) NSArray *showErrorMessageApiArray;
@property (nonatomic, strong) NSArray *notHiddenLoadingMessageApiArray;
@property (nonatomic, strong) NSArray *logMessageApiArray;


@end

@implementation TJNetworking

static TJNetworking *_network = nil;

+ (TJNetworking *)shareNetwork {
    return [[TJNetworking alloc] init];
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (_network == nil) {
            _network = [super allocWithZone:zone];
        }
    });
    return _network;
}

- (void)POST:(NSString *)url parameters:(id)parameters success:(void (^)(NSDictionary * _Nonnull, id _Nonnull))success failure:(void (^)(NSError * _Nonnull))failure {
    [self dataTaskWithMethod:@"POST" urlString:url isJson:NO parameters:parameters success:^(id _Nullable responseObject) {
        [self handleResponseObject:responseObject url:url success:success failure:failure];
    } failure:^(NSError *error) {
        [self handleError:error url:url failure:failure];
    }];
}

- (void)POSTBodyJSON:(NSString *)url parameters:(nullable id)parameters success:(void (^__nullable)(NSDictionary *responseObject, id data))success failure:(void (^__nullable)(NSError *error))failure {
    [self dataTaskWithMethod:@"POST" urlString:url isJson:YES parameters:parameters success:^(id _Nullable responseObject) {
        [self handleResponseObject:responseObject url:url success:success failure:failure];
    } failure:^(NSError *error) {
        [self handleError:error url:url failure:failure];
    }];
}

- (void)GET:(NSString *)url parameters:(id)parameters success:(void (^)(NSDictionary * _Nonnull, id _Nonnull))success failure:(void (^)(NSError * _Nonnull))failure {
    [self dataTaskWithMethod:@"GET" urlString:url isJson:YES parameters:parameters success:^(id _Nullable responseObject) {
        [self handleResponseObject:responseObject url:url success:success failure:failure];
    } failure:^(NSError *error) {
        [self handleError:error url:url failure:failure];
    }];
}

- (void)dataTaskWithMethod:(NSString *)method
                 urlString:(NSString *)urlString
                    isJson:(BOOL)isJson
                parameters:(nullable id)parameters
                   success:(void (^)(id  _Nullable responseObject))success failure:(void (^)(NSError * error))failure {
    
    NSDate *startDate = [NSDate date];
    NSString *url = [self getRequestUrlWithUrl:urlString];
    NSMutableDictionary *headers = [self addCommonHeaderWithUrl:urlString];
    
    AFHTTPSessionManager *sessionManager = isJson ? getBodyJsonHTTPSessionManager() : getHTTPSessionManager();
    NSURLSessionDataTask *dataTask = [sessionManager dataTaskWithHTTPMethod:method URLString:url parameters:parameters headers:headers uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        //        if ([self.logMessageApiArray containsObject:urlString]) {
        TJDetailLog(@"method = %@, urlString = %@, parameters = %@, headers = %@ 耗时 = %.2f \n responseObject = %@", method, url, parameters, headers, [NSDate date].timeIntervalSince1970 - startDate.timeIntervalSince1970, responseObject);
        //        }
        
        if (success) {
            success(responseObject);
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        TJDetailLog(@"method = %@, urlString = %@, parameters = %@, headers = %@ 耗时 = %.2f \n error = %@", method, url, parameters, headers, [NSDate date].timeIntervalSince1970 - startDate.timeIntervalSince1970, error);
        if (failure) {
            failure(error);
        }
    }];
    [dataTask resume];
}

- (void)handleError:(NSError *)error url:(NSString *)url  failure:(void (^)(NSError * _Nonnull))failure {
    
    if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == -1009) {
        [TJHUD showErrorMessage:@"Network error"];
        if (failure) {
            failure(error);
        }
        return;
    }
    
    NSDictionary *responseObject = [error getAFNOperationFailingURLResponseData];
    if (!responseObject) {
        if (failure) {
            failure(error);
        }
        return;
    }
    
    int resCode = [responseObject[@"code"] intValue];
    NSString *message = responseObject[@"msg"];
    
    if (resCode == 402 || resCode == 401) {
        [self tokenErrorWithCode:resCode message:message];
        return;
    }
    
    if ([self.showErrorMessageApiArray containsObject:url]) {
        if (error.code == NSURLErrorTimedOut) {
            [TJHUD hiddenLoading];
            [TJHUD showErrorMessage:@"The request timed out"];
        } else {
            
        }
    }
    
    if (failure) {
        NSMutableDictionary *errorDict = @{}.mutableCopy;
        [errorDict setValue:message forKey:NSLocalizedFailureReasonErrorKey];
        [errorDict setValue:responseObject forKey:@"responseObject"];
        failure([NSError errorWithCode:resCode userInfo:errorDict]);
    }
}

- (void)tokenErrorWithCode:(int)code message:(NSString *)message {
    if (!TJUserInfo.isLogin) {
        return;
    }
    [TJHUD hiddenLoading];
    [[NSNotificationCenter defaultCenter] postNotificationName:tokenErrorNotification object:nil userInfo:nil];
    TJUserInfo.isLogin = NO;
    TJUserInfo.token = nil;
    [TJAlertController alertInController:getMainController() title:nil message:message left:nil right:^(TJAlertAction * _Nonnull action) {
        action.title = @"好的";
        action.titleColor = UIColor.tj_mainColor;
    }];
}

- (void)handleResponseObject:(NSDictionary *)responseObject url:(NSString *)url success:(void (^)(NSDictionary * _Nonnull, id _Nonnull))success failure:(void (^)(NSError * _Nonnull))failure  {
    
    if (![responseObject isKindOfClass:NSDictionary.class]) return ;
    if (!responseObject.allKeys.count) return;
    int code = [responseObject[@"code"] intValue];
    
    if (![self.notHiddenLoadingMessageApiArray containsObject:url] && TJTools.tool.currentHud) {
        
        MBProgressHUD *hud = TJTools.tool.currentHud;
        TJLoadingView *loadingView = (TJLoadingView *)hud.customView;
        if ([loadingView isKindOfClass:TJLoadingView.class]) {
            [loadingView stopAnimating];
            [hud hideAnimated:NO];
            TJTools.tool.currentHud = nil;
        }
    }
    
    
    if (code == 0 || code == 200) {
        if (success) {
            id data = responseObject[@"data"];
            
            if ([data isKindOfClass:NSNull.class]) {
                NSMutableDictionary *handleDict = [NSMutableDictionary dictionaryWithDictionary:responseObject];
                [handleDict removeObjectForKey:@"data"];
                success(handleDict, handleDict[@"data"]);
            } else {
                if ([data isKindOfClass:NSDictionary.class] && [data[@"list"] isKindOfClass:NSNull.class]) {
                    NSMutableDictionary *handleDict = [NSMutableDictionary dictionaryWithDictionary:responseObject];
                    [handleDict removeObjectForKey:@"data"];
                    success(handleDict, handleDict[@"data"]);
                } else {
                    success(responseObject, responseObject[@"data"]);
                }
            }
        }
        return;
    }
    
    NSString *message = responseObject[@"msg"];
    if ([self.showErrorMessageApiArray containsObject:url] && !isEmptyString(message)) {
        [TJHUD showErrorMessage:message];
    }
    
    //1301是被挤了, 1300和1302是登录过期
    if (code == 402 || code == 401) {
        [self tokenErrorWithCode:code message:message];
        return;
    }
    
    if (failure) {
        NSMutableDictionary *errorDict = @{}.mutableCopy;
        [errorDict setValue:message forKey:NSLocalizedFailureReasonErrorKey];
        [errorDict setValue:responseObject forKey:@"responseObject"];
        failure([NSError errorWithCode:code userInfo:errorDict]);
    }
    
}

- (NSString *)getRequestUrlWithUrl:(NSString *)url {
    if ([url containsString:@"http"]) {
        return url;
    }
    return [NSString stringWithFormat:@"%@%@", getBaseUrlString(), url];
}

- (BOOL)headerIsAddTokenWithUrl:(NSString *)url {
    if (TJUserInfo.isLogin && !isEmptyString(TJUserInfo.token)) {
        return YES;
    }
    return NO;
}

- (NSMutableDictionary *)addCommonHeaderWithUrl:(NSString *)url {
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    [dictionary setValue:@"2" forKey:@"X-Tenant-Id"];
    [dictionary setValue:@"rrbd10" forKey:@"channel"];

    if ([self headerIsAddTokenWithUrl:url]) {
        [dictionary setValue:TJUserInfo.token forKey:@"Authorization"];
    }
    return dictionary;
}

- (NSArray *)showErrorMessageApiArray {
    if (!_showErrorMessageApiArray) {
        _showErrorMessageApiArray = @[
            @"/user/appUser/createStaff",
            @"/user/appUser/updatePoi",
            @"/user/appUser/userEnable",
            @"/user/appUser/userDisable",
            @"/user/appUser/userDelete",
            @"/user/userGroup/delete",
            @"/user/userGroup/updateName",
            @"/user/appUser/checkPoi",
            @"/user/appUser/updatePoi",
            @"/user/appUser/updateUserRealName",
            @"/escrow/clockPlan/updateStatus",
            @"/escrow/clockPlan/toClockPlan",
            @"/escrow/appTemplate/editVideo",
            @"/escrow/appTemplate/toClock",
            @"/user/appUser/updatePassword",
            @"/user/appUser/retrievePassword",
            @"/escrow/common/sendCaptchaNoLogin",
        ];
    }
    return _showErrorMessageApiArray;
}

- (NSArray *)logMessageApiArray {
    if (!_logMessageApiArray) {
        _logMessageApiArray = @[
        ];
    }
    return _logMessageApiArray;
}

- (NSArray *)notHiddenLoadingMessageApiArray {
    if (!_notHiddenLoadingMessageApiArray) {
        _notHiddenLoadingMessageApiArray = @[
            @"/escrow/appTemplate/editVideo",
            @"/escrow/appTemplate/getTaskStatus",
        ];
    }
    return _notHiddenLoadingMessageApiArray;
}

AFHTTPSessionManager *_bodyJsonSessionManager;
AFHTTPSessionManager * getBodyJsonHTTPSessionManager(void) {
    if (!_bodyJsonSessionManager) {
        _bodyJsonSessionManager = [AFHTTPSessionManager manager];
        _bodyJsonSessionManager.requestSerializer = [AFJSONRequestSerializer serializer];
        AFJSONResponseSerializer *JSONResponseSerializer = [AFJSONResponseSerializer serializer];
        _bodyJsonSessionManager.responseSerializer = JSONResponseSerializer;
        JSONResponseSerializer.removesKeysWithNullValues = YES;
        _bodyJsonSessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", @"text/html", nil];
        [_bodyJsonSessionManager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
        _bodyJsonSessionManager.requestSerializer.timeoutInterval = 15.f;
        [_bodyJsonSessionManager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
        
    }
    return _bodyJsonSessionManager;
}


- (void)uploadFileWithURL:(NSString *)url
                 fileData:(NSData *)fileData
                  fileKey:(NSString *)fileKey
                 fileName:(NSString *)fileName
                 mimeType:(NSString *)mimeType
               parameters:(nullable id)parameters
                  success:(void (^)(NSDictionary *, id data))success
                  failure:(void (^)(NSError *error))failure {
    
    NSString *urlString = [self getRequestUrlWithUrl:url];
    NSMutableDictionary *headers = [self addCommonHeaderWithUrl:urlString];
    
    NSDate *startDate = [NSDate date];
    
    [getHTTPSessionManager() POST:urlString parameters:parameters headers:headers constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        [formData appendPartWithFileData:fileData name:fileKey fileName:fileName mimeType:mimeType];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        TJDetailLog(@" urlString = %@, parameters = %@, headers = %@ 耗时 = %.2f \n responseObject = %@", url, parameters, headers, [NSDate date].timeIntervalSince1970 - startDate.timeIntervalSince1970, responseObject);

        [self handleResponseObject:responseObject url:url success:success failure:failure];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        TJDetailLog(@"urlString = %@, parameters = %@, headers = %@ 耗时 = %.2f \n error = %@", url, parameters, headers, [NSDate date].timeIntervalSince1970 - startDate.timeIntervalSince1970, error);
        
        [self handleError:error url:url failure:failure];
    }];
}

NSURLSessionDownloadTask * TJDownloadFileWithUrl(NSString *url,void (^progress)(CGFloat value), NSURL *(^destination)(void), void (^complete)(NSError * _Nullable error)) {
    
    if (isEmptyString(url)) {
        complete([NSError errorWithCode:-10001 errorReason:@"url错误"]);
        return nil;
    }
    
    AFURLSessionManager *sessionManager = [[AFURLSessionManager alloc] init];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url.URL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];
    NSURLSessionDownloadTask *task = [sessionManager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        dispatch_async_main_queue(^{
            progress(downloadProgress.fractionCompleted);
        });
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        return destination();
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        dispatch_async_main_queue(^{
            complete(error);
        });
    }];
    [task resume];
    return task;
}


NSURLSessionUploadTask * TJUploadFileWithLocalPath(NSString *localPath, NSString *destinationPath, void (^progress)(CGFloat value), void (^complete)(NSError * _Nullable error, NSString * _Nullable ocId, NSDate * _Nullable date)) {
    
    AFURLSessionManager *sessionManager = [[AFURLSessionManager alloc] init];
    
    if (![[NSFileManager defaultManager] fileExistsAtPath:localPath]) {
        complete([NSError errorWithCode:-10000 errorReason:@"不存在本地文件"], nil, nil);
        return nil;
    }
 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:destinationPath.URL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];
    request.HTTPMethod = @"POST";
    [request setValue:[NSString stringWithFormat:@"%lld", getSizeInBytesByPath(localPath)] forHTTPHeaderField:@"Content-Length"];
    [request setValue:TJUserInfo.token forHTTPHeaderField:@"Authorization"];
    [request setValue:[NSString stringWithFormat:@"%@", HJContentTypeForPathExtension(localPath.pathExtension)] forHTTPHeaderField:@"Content-Type"];
 
    NSURLSessionUploadTask *task = [sessionManager uploadTaskWithRequest:request fromFile:[NSURL fileURLWithPath:localPath] progress:^(NSProgress * _Nonnull uploadProgress) {
        dispatch_async_main_queue(^{
            progress(uploadProgress.fractionCompleted);
        });
    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        NSLog(@"responseObject = %@", responseObject);
    }];
    
    [task resume];
    return task;
}


@end


